package com.etlmaster.executor.trans.core;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.etlmaster.executor.utils.JsonHelper;

/**
 * Created by wugf on 2016/12/12. 实时处理的流对象
 */
public class Line implements Serializable {

	private String[] fieldList;
	private int length;
	private int fieldNum;
	public static final int LINE_MAX_FIELD = 1024;

	private LineMeta meta;
	private Map<String, Object> extra;
	private boolean skip = false;

	private List<Map<String, Object>> targetRowData = new ArrayList<Map<String, Object>>();

	public Line() {
		this.fieldList = new String[LINE_MAX_FIELD];
	}

	public Line(LineMeta meta) {
		this.fieldList = new String[LINE_MAX_FIELD];
		this.setMeta(meta);
	}

	public void clear() {
		length = 0;
		fieldNum = 0;
	}

	public int length() {
		return length;
	}

	/*
	 * private void updateIndex() { getColIndex().clear(); for (int i = 0; i <
	 * fieldNum; i++) { getColIndex().put( fieldList[i].getFieldTable() + "_" +
	 * fieldList[i].getFieldName(), i); } }
	
	public boolean addField(String field) {
		fieldList[fieldNum] = field;
		fieldNum++;
		if (field != null) {
			length += field.length();
		}
		return true;
	} */

	public boolean addField(String field, String tableName, String fieldName) {
		
		if(getMeta().getColIndex().containsKey(tableName.toUpperCase()+"_"+fieldName.toUpperCase())){
		}else{
			getMeta().addField(tableName, fieldName);
		}
		int position = getMeta().getColPosition(tableName + "_" + fieldName);
		fieldList[position] = field;
		fieldNum++;
		if (field != null) {
			length += field.length();
		}
		return true;
	}

	public int getFieldNum() {
		return fieldNum;
	}

	public String getField(int idx) {
		return fieldList[idx];
	}

	public String checkAndGetField(int idx) {
		if (idx < 0 || idx >= fieldNum) {
			return null;
		}
		return fieldList[idx];
	}

	public StringBuffer toStringBuffer(String separator) {
		StringBuffer tmp = new StringBuffer();
		for (int i = 0; i < meta.getCounter(); i++) {
			if (!meta.getFieldMetas()[i].isDelete()) {
				tmp.append(fieldList[i]);
				if (i < fieldNum - 1) {
					tmp.append(separator);
				}
			}
		}
		return tmp;
	}

	public String toString(String separator) {
		return this.toStringBuffer(separator).toString();
	}

	public static Line fromJson(String tableName, String lineJson,LineMeta meta) {

		Map<String, String> map = (Map<String, String>) JsonHelper
				.getInstance().read(lineJson);

		return fromMap(tableName, map,meta);
	}

	public static Line fromMap(String tableName, Map map,LineMeta meta) {
		Line line = new Line(meta);
		Iterator iter = map.entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			String value = "";
			if (entry.getValue() instanceof Map) {
				value = JsonHelper.getInstance().write(entry.getValue());
			} else {
				value = (String) entry.getValue();
			}
			line.addField(value, tableName, (String) entry.getKey());
		}
		return line;
	}

	public static Line fromString(String tableName, String lineStr,
			String separator, String[] cols) throws Exception {
		String strs[] = lineStr.split(separator);
		Line line = new Line();

		if (cols != null) {
			for (int i = 0; i < strs.length; i++) {
				line.addField(strs[i], tableName, cols[i]);
			}
		} else {
			/*
			for (int i = 0; i < strs.length; i++) {
				line.addField(cols[i]);
			}*/
		}
		return line;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + Arrays.hashCode(fieldList);
		result = prime * result + fieldNum;
		result = prime * result + length;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Line other = (Line) obj;
		if (!Arrays.equals(fieldList, other.fieldList))
			return false;
		if (fieldNum != other.fieldNum)
			return false;
		if (length != other.length)
			return false;
		return true;
	}

	public boolean replaceField(String field, int index) {
		if (index > fieldList.length || index < 0) {
			return false;
		}
		length = length - fieldList[index].length() + field.length();
		fieldList[index] = field;
		return true;
	}

	/*
	 * public boolean replaceFieldName(String sourceTab, String sourceName,
	 * String targetName) {
	 * 
	 * Integer sourceIndex = this.getColIndex().get( sourceTab + "_" +
	 * sourceName); if (sourceIndex == null) { return false; }
	 * fieldList[sourceIndex].setFieldName(targetName);
	 * this.getColIndex().remove(sourceTab + "_" + sourceName);
	 * this.getColIndex().put(sourceTab + "_" + targetName, sourceIndex); return
	 * true; }
	 * 
	 * public boolean replaceFieldName(String sourceTab, String sourceName,
	 * String targetTable, String targetName) {
	 * 
	 * Integer sourceIndex = this.getColIndex().get( sourceTab + "_" +
	 * sourceName); if (sourceIndex == null) { return false; }
	 * fieldList[sourceIndex].setFieldName(targetName);
	 * fieldList[sourceIndex].setFieldTable(targetTable);
	 * this.getColIndex().remove(sourceTab + "_" + sourceName);
	 * this.getColIndex().put(targetTable + "_" + targetName, sourceIndex);
	 * return true; }
	 * 
	 * public boolean replaceTabName(String targetTab) {
	 * 
	 * for (int i = 0; i < fieldNum; i++) {
	 * fieldList[i].setFieldTable(targetTab); } updateIndex(); return true; }
	 */
	public boolean isSkip() {
		return skip;
	}

	public void setSkip(boolean skip) {
		this.skip = skip;
	}

	/*
	 * public void deleteField(int index) { if (index < fieldNum) {
	 * if(fieldList[index].getFieldValue()!=null) length = length -
	 * fieldList[index].getFieldValue().length(); for (int i = index; i <
	 * fieldNum; i++) { fieldList[i] = fieldList[i + 1]; } fieldNum--; }
	 * updateIndex(); }
	 * 
	 * public Map toMap() { Map<String, String> map = new HashMap<String,
	 * String>(); for (int i = 0; i < fieldNum; i++) { FieldEntry entry =
	 * this.fieldList[i]; map.put(entry.getFieldName(), entry.getFieldValue());
	 * } return map; }
	 */
	public String toJson() {

		StringBuffer sb = new StringBuffer();
		sb.append("{");
		for (int i = 0; i < fieldNum; i++) {
			FieldEntry entry = getMeta().getFieldMetas()[i];
			sb.append("\"" + entry.getTargetFieldName() + "\":\""
					+ fieldList[i] + "\",");

		}
		sb.deleteCharAt(sb.length() - 1);
		sb.append("}");

		return sb.toString();

	}

	public String toJsons() {
		Map<String, StringBuffer> map = new HashMap<String, StringBuffer>();

		for (int i = 0; i < fieldNum; i++) {
			FieldEntry entry = getMeta().getFieldMetas()[i];
			StringBuffer sb = map.get(entry.getTargetTable());
			if (sb == null) {
				sb = new StringBuffer();
				sb.append("{");
				map.put(entry.getTargetTable(), sb);
			}
			sb.append("\"" + entry.getTargetFieldName() + "\":\""
					+ fieldList[i] + "\",");

		}
		StringBuffer sb = new StringBuffer();
		sb.append("[");
		Iterator it = map.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry<String, StringBuffer> entry = (Entry<String, StringBuffer>) it
					.next();
			if (extra != null) {
				sb.append(JsonHelper.getInstance().write(extra));
				sb.deleteCharAt(sb.length() - 1);
				sb.append(",");
			} else {
				sb.append("{");
			}
			sb.append("\"tableName\":\"" + entry.getKey() + "\",\"data\":{")
					.append(entry.getValue().deleteCharAt(0)
							.deleteCharAt(entry.getValue().length() - 1)
							+ "}},");

		}
		sb.deleteCharAt(sb.length() - 1);
		sb.append("]");

		return sb.toString();

	}

	public Map<String, Object> getExtra() {
		return extra;
	}

	public void setExtra(Map<String, Object> extra) {
		this.extra = extra;
	}

	public List<Map<String, Object>> getTargetRowData() {
		return targetRowData;
	}

	public void setTargetRowData(List<Map<String, Object>> targetRowData) {
		this.targetRowData = targetRowData;
	}

	public LineMeta getMeta() {
		return meta;
	}

	public void setMeta(LineMeta meta) {
		this.meta = meta;
	}

}
